/**
 * Depend on jQuery
 */
Date.prototype.getDaysInMonth = function(){
	return new Date(this.getFullYear(), this.getMonth()+1, 0).getDate();
};
Date.prototype.equalDay = function(targetDate){
	if(this.getFullYear() != targetDate.getFullYear()){
		return false;
	}
	if(this.getMonth() != targetDate.getMonth()){
		return false;
	}
	if(this.getDate() != targetDate.getDate()){
		return false;
	}
	return true;
};
var WEEK = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
var MONTH = ["January", "Febrary", "March", "April", "May", "June", "July", "Augest", "September", "October", "November", "December"];
function Calendar(containerId, callback){
	this.containerId = containerId;
	this.currentMonth = new Date();
	if(callback){
		this.callback = callback;
	}else{
		this.callback = function(date){};
	}
	this.show=function(targetMonth){
		if(targetMonth){
			if((typeof targetMonth=='object')&&targetMonth.constructor==Date){
				this.currentMonth = targetMonth;
			}else if((typeof targetMonth=='string')&&targetMonth.constructor==String){
				this.currentMonth = this.parseDateFromString(targetMonth);
			}
		}
		this.create();
	};
	
	this.showAndSelectDate = function(selectedDate){
		if(selectedDate){
			if((typeof selectedDate=='object')&&selectedDate.constructor==Date){
				this.selectedDate = selectedDate;
			}else if((typeof selectedDate=='string')&&selectedDate.constructor==String){
				this.selectedDate = this.parseDateFromString(selectedDate);
			}
		}
		this.show(selectedDate);
		if(this.selectedDate){
			try{
				this.callback(this.selectedDate.getFullYear()+"-"+(this.selectedDate.getMonth()+1)+"-"+this.selectedDate.getDate());
			}catch(err){
			  txt="There is an error when invoke callback function:\n\n";
			  txt+="Description: " + err.description + "\n\n";
			  alert(txt);
			  return;
			}
		}
	};
	
	this.parseDateFromString=function(date){
		var targetDateArray = date.split("-");
		if(targetDateArray.length == 2){
			return new Date(targetDateArray[0], targetDateArray[1]-1, 1);
		}else{
			return new Date(targetDateArray[0], targetDateArray[1]-1, targetDateArray[2]);
		}
	};
	
	this.create=function(){
		var outDiv = $("<div style=\"border:1px solid #CCCCCC; width:100%;\"  align=\"center\" ></div>");
		this.outDiv = outDiv;
		var calendarTable = $("<table cellpadding=\"0\" cellspacing=\"0\" style=\"width:100%;border-top:1px solid #CCCCCC;border-left:1px solid #CCCCCC;text-align:center;\">");
		var headerTD = $("<td style=\"border-right:1px solid #CCCCCC;border-bottom:1px solid #CCCCCC;font-size:20px;text-align:center;\" colspan=\"7\"></td>");
		var previousImg = $("<a style=\"text-decoration: none;font-size:16px;\" href=\"javascript:void(0);\">previous</a>");
		previousImg.bind("click", {calInstance:this},this.prevousMonth);
		var nextImg = $("<a style=\"text-decoration: none;font-size:16px;\" href=\"javascript:void(0);\">next</a>");
		nextImg.bind("click",  {calInstance:this},this.nextMonth);
		headerTD.append(previousImg);
		headerTD.append("&nbsp;&nbsp;");
		headerTD.append(this.currentMonth.getFullYear()+" "+MONTH[this.currentMonth.getMonth()]);
		headerTD.append("&nbsp;&nbsp;");
		headerTD.append(nextImg);
		var headerTR = $("<tr style=\"height:25px;\"></tr>").append(headerTD);
		calendarTable.append(headerTR);
		var dayCount = this.currentMonth.getDaysInMonth();
		
		var calendarTR = $("<tr style=\"height:25px;\"></tr>");
		for(var i = 1; i <= 7; i++){
			var calendarWeekTD = $("<td style=\"background-color:#DDDDDF;border-right:1px solid #CCCCCC;border-bottom:1px solid #CCCCCC;font-size:16px;font-weight:bold;\"></td>");
			calendarWeekTD.html(WEEK[i-1]);
			calendarTR.append(calendarWeekTD);
		}
		calendarTable.append(calendarTR);
		var today = new Date();
		for(var i = 1; i <= dayCount; i++){
			var day = new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth(), i);
			var dayInWeek = day.getDay();
			if(dayInWeek == 0 || i == 1){
				calendarTR = $("<tr style=\"height:25px;\"></tr>");
			}
			var dayTDStr = "<td class=\"singleDay\" style=\"border-right:1px solid #CCCCCC;border-bottom:1px solid #CCCCCC;font-size:16px;\"></td>";
			var calendarDayTD;
			//Append empty tds
			if(i == 1){
				for(var j = 0; j < dayInWeek; j++){
					calendarDayTD = $(dayTDStr);
					calendarDayTD.html("&nbsp;");
					calendarTR.append(calendarDayTD);
				}
			}
			calendarDayTD = $(dayTDStr);
			calendarDayTD.html(i);
			calendarDayTD.bind("click", {date:day.getFullYear()+"-"+(day.getMonth()+1)+"-"+day.getDate(), calInstance: this}, this.clickEvent);
			calendarDayTD.hover(this.hoverOverEvent, this.hoverOutEvent);
			if(day.equalDay(today)){
				calendarDayTD.addClass("today");
				calendarDayTD.css({"font-weight":"bold", "font-size": "20", "color":"red"});
			}
			
			if(this.selectedDate && day.equalDay(this.selectedDate)){
				calendarDayTD.attr("selected",true);
				calendarDayTD.css({"background-color":"#EEEEEE", "font-weight":"bold", "font-size": "20"});
			}
			calendarTR.append(calendarDayTD);
			//Append empty tds
			if(i == dayCount){
				for(var j = dayInWeek+1; j <= 6; j++){
					calendarDayTD = $(dayTDStr);
					calendarDayTD.html("&nbsp;");
					calendarTR.append(calendarDayTD);
				}
			}
			if(dayInWeek == 6 || i == dayCount){
				calendarTable.append(calendarTR);
			}
		}
		outDiv.append(calendarTable);
		$("#"+this.containerId).html("");
		$("#"+this.containerId).append(outDiv);
	};
	
	this.getNextMonthDate = function(){
		return new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth()+1, 1);
	};
	
	this.nextMonth = function(event){
		calInstance = event.data.calInstance;
		calInstance.show(calInstance.getNextMonthDate());
	};
	
	this.getPreviousMonthDate = function(){
		return new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth()-1, 1);
	};
	
	this.prevousMonth=function(event){
		calInstance = event.data.calInstance;
		calInstance.show(calInstance.getPreviousMonthDate());
	};
	
	this.clickEvent = function(event){
		var clickDay = event.data.date;
		var calInstance = event.data.calInstance;
		try{
			calInstance.callback(clickDay);
		}catch(err){
		  txt="There is an error when invoke callback function:\n\n";
		  txt+="Description: " + err.description + "\n\n";
		  alert(txt);
		  return;
		}
		calInstance.outDiv.find("td.singleDay").css({"background-color":"", "font-weight":"", "font-size": "16"});
		calInstance.outDiv.find("td.singleDay").attr("selected",false);
		calInstance.outDiv.find("td.today").css({"font-weight":"bold", "font-size": "20", "color":"red"});
		
		$(this).css({"background-color":"#EEEEEE", "font-weight":"bold", "font-size": "20"});
		$(this).attr("selected", true);
	};
	
	this.hoverOverEvent = function(event){
		if(!$(this).attr("selected")){
			$(this).css({"background-color":"#EEEEEE"});
		}
	};
	
	this.hoverOutEvent = function(event){
		if(!$(this).attr("selected")){
			$(this).css({"background-color":""});
		}
	};
}
